package jdk5.generics.effective;

import java.util.ArrayList;
import java.util.List;

public class ListPriorToTheArray {
    public static void main(String[] args) {
        // 1. 数组协变, 列表不可变, 数组存在缺陷
        failsAtRuntime();
        willNotComplie();

        // 2. 用列表代替数组


    }

    static void failsAtRuntime() {
        Object[] objects = new Long[1];
        // java.lang.ArrayStoreException: java.lang.String
        objects[0] = "I don't fit in";
    }

    static void willNotComplie() {
        // Incompatible types
//        List<Object> objects = new ArrayList<Long>();
//        objects.add("I don't fit in");
    }

    // Reduction without generics, and with concurrency flaw
    static Object reduce(List list, Function f, Object initValue) {
        synchronized (list) {
            Object result = initValue;
            for (Object o : list) {
                // 不要从同步区域调用外来方法
                result = f.apply(result, o);
            }
            return result;
        }
    }

    // 1.5 之前
    // Reduction without generics or concurrency flaw
    static Object reduce1(List list, Function f, Object initValue) {
        Object[] snapshot = list.toArray();
        Object result = initValue;
        for (Object o : snapshot) {
            result = f.apply(result, o);
        }
        return result;
    }

    // 泛型代替数组
    // List-based generics reduction
    static <E> E reduce2(List<E> list, Function2<E> f, E initValue) {
        List<E> snapshot;
        synchronized (list) {
            snapshot = new ArrayList<E>(list);
        }

        E result = initValue;
        for (E e : snapshot) {
            result = f.apply(result, e);
        }
        return result;
    }

}

interface Function {
    Object apply(Object obj, Object obj2);
}

interface Function2<E>{
    E apply(E e, E e2);
}